package com.original.simuladoresws.controller;

import java.math.BigDecimal;

import org.springframework.stereotype.Controller;

import com.original.simuladoresws.constant.CommonConstant;
import com.original.simuladoresws.entities.TbTaxIndex;
import com.original.simuladoresws.entities.soap.SOAPObjectiveCalculateInput;
import com.original.simuladoresws.entities.soap.SOAPObjectiveCalculateOutput;
import com.original.simuladoresws.service.TaxIndexService;
import com.original.simuladoresws.service.impl.TaxIndexServiceImpl;

@Controller
public class ObjectiveCalculateController {
	TaxIndexService taxIndexService = new TaxIndexServiceImpl();
	
	public SOAPObjectiveCalculateOutput getObjectiveCalculate(SOAPObjectiveCalculateInput input) {
		SOAPObjectiveCalculateOutput output = new SOAPObjectiveCalculateOutput();
		SOAPObjectiveCalculateOutput normal;
		SOAPObjectiveCalculateOutput retir;
		// retirement is false
		BigDecimal invested_ammount = null;
		BigDecimal invested_ammount_rental = null;
		BigDecimal missing_ammount = null;
		BigDecimal extra_credit = null;
		// retirement is true
		// Tax_Key = "SIM_OBJETIVO_INFLACAO_MENSAL"
		TbTaxIndex taxIndex = taxIndexService.read(CommonConstant.TAX_KEY);
		BigDecimal monthly_infraction = null;
		
		if (taxIndex != null && taxIndex.getVlTaxAmount() != null) {
			monthly_infraction = taxIndex.getVlTaxAmount();
		}
		
		BigDecimal investiment_monthly_tax = null;
		BigDecimal investiment_monthly_tax_temp = BigDecimal.valueOf(Double.valueOf("0"));
		Integer contribution_time = null;
		Integer retirement_time = null;
		Integer liquid_tax = null;
		Integer monthly_income_percentual = null;
		Integer total_income_percentual = null;
		Integer reinvestment_income_percentual = null;
		BigDecimal total_applied_value = null;
		BigDecimal total_initial_ammount_income = null;
		BigDecimal total_monthly_applied_income = null;
		BigDecimal Invested_ammount_rental = null;
		BigDecimal future_revenue = null;
		BigDecimal recomended_monthly_application = null;
		
		if (input != null) {
			// Calculate
			if (input.getRetirement()) {
				investiment_monthly_tax = input.getSuitability_Tax();
				contribution_time = (input.getRetirement_Start_Age() - input.getCurrent_Age()) * 12;
				retirement_time = (input.getRetirement_Finish_Age() - input.getRetirement_Start_Age()) * 12;
				liquid_tax = (1 + investiment_monthly_tax.intValue())
						/ (1 + monthly_infraction.intValue());
				
				monthly_income_percentual = liquid_tax ^ retirement_time;
				total_income_percentual = (1 - liquid_tax ^ contribution_time) / (1 - liquid_tax) - 1;
				reinvestment_income_percentual = (1 - liquid_tax) * liquid_tax ^ retirement_time / (1 - liquid_tax ^ retirement_time);
				Float monthlyApp = Float.valueOf(input.getMonthly_Application().toString());
				total_applied_value = BigDecimal.valueOf(Double.valueOf(input.getInitial_Amount().toString()) 
						+ Double.valueOf(input.getMonthly_Application().toString()) * contribution_time);
				total_initial_ammount_income = BigDecimal.valueOf(Double.valueOf(input.getInitial_Amount().toString()) * monthly_income_percentual);
				total_monthly_applied_income = BigDecimal.valueOf(Double.valueOf(input.getMonthly_Application().toString()) * total_income_percentual);
				Invested_ammount_rental = BigDecimal.valueOf(Double.valueOf(total_initial_ammount_income.toString()) + Double.valueOf(total_monthly_applied_income.toString()));
				future_revenue = BigDecimal.valueOf(Double.valueOf(Invested_ammount_rental.toString()) * ((1 - liquid_tax) * liquid_tax ^ retirement_time) / (1 - liquid_tax ^ (retirement_time + 1)));

				recomended_monthly_application = BigDecimal.valueOf(((1 / reinvestment_income_percentual) * Double.valueOf(input.getRequired_Amount().toString()) 
						- Double.valueOf(input.getInitial_Amount().toString())	* monthly_income_percentual) / total_income_percentual);
			} else {
				invested_ammount = BigDecimal.valueOf(Double.valueOf(input.getInitial_Amount().toString()) 
						+ (Double.valueOf(input.getMonthly_Application().toString()) 
								* (Double.valueOf(input.getInvestment_Time()) * Double.valueOf(input.getInvestment_Time_Type().toString()))));
				if (input.getSuitability_Tax() != null) {
					investiment_monthly_tax_temp = input.getSuitability_Tax();
				}
				invested_ammount_rental = BigDecimal.valueOf(((Double.valueOf(input.getInitial_Amount().toString())
						* (((1 + Integer.valueOf(investiment_monthly_tax_temp.toString())) 
								^ (input.getInvestment_Time() * input.getInvestment_Time_Type()) + 1) - 1) 
								/ Double.valueOf(input.getSuitability_Tax().toString())) - Double.valueOf(input.getMonthly_Application().toString()))
						+ (Double.valueOf(input.getInitial_Amount().toString()) * ((1 + Integer.valueOf(investiment_monthly_tax_temp.toString()))
								^ (input.getInvestment_Time() * input.getInvestment_Time_Type()))));
				
				missing_ammount = BigDecimal.valueOf(Double.valueOf(input.getRequired_Amount().toString()) - Double.valueOf(invested_ammount_rental.toString()));
				extra_credit = BigDecimal.valueOf(Double.valueOf(invested_ammount_rental.toString()) - Double.valueOf(input.getRequired_Amount().toString()));
			}
			
			// set data into object
			if (input.getRetirement()) {
				retir = new SOAPObjectiveCalculateOutput();
				retir.setRetirement(input.getRetirement());
				retir.setObjective(input.getObjective());
				retir.setInitial_amount(input.getInitial_Amount());
				retir.setRequired_amount(input.getRequired_Amount());
				retir.setMonthly_application(input.getMonthly_Application());
				retir.setInvestment_time(input.getInvestment_Time());
				retir.setInvestment_time_type(input.getInvestment_Time_Type());
				retir.setSuitability_tax(input.getSuitability_Tax());
				retir.setCurrent_age(input.getCurrent_Age());
				retir.setRetirement_start_age(input.getRetirement_Start_Age());
				retir.setRetirement_finish_age(input.getRetirement_Finish_Age());
				retir.setInvested_ammount(invested_ammount);
				retir.setMissing_ammount(missing_ammount);
				retir.setinvested_ammount_rental(invested_ammount_rental);
				retir.setExtra_credit(extra_credit);
				retir.setRetirement_time(retirement_time);
				retir.setContribution_time(contribution_time);
				retir.setTotal_initial_ammount_income(total_initial_ammount_income);
				retir.setTotal_monthly_applied_income(total_monthly_applied_income);
				retir.setInvested_ammount_rental(Invested_ammount_rental);
				retir.setFuture_revenue(future_revenue);
				retir.setRecomended_monthly_application(recomended_monthly_application);
				
				if (input.getRetirement() != null || input.getObjective() != null
						|| input.getInitial_Amount() != null || input.getRequired_Amount() != null
						
						|| input.getMonthly_Application() != null || input.getInvestment_Time() != null
						|| input.getInvestment_Time_Type() != null || input.getSuitability_Tax() != null
						|| input.getCurrent_Age() != null || input.getRetirement_Start_Age() != null
						|| input.getRetirement_Finish_Age() != null || invested_ammount != null
						|| missing_ammount != null
						|| invested_ammount_rental != null || extra_credit != null
						|| retirement_time != null || contribution_time != null
						|| total_initial_ammount_income != null
						|| total_monthly_applied_income != null
						|| Invested_ammount_rental != null
						|| future_revenue != null
						|| recomended_monthly_application != null) {
					retir.setError(false);
					retir.setMessage("");
				} else {
					retir.setError(true);
					retir.setMessage("");
				}
				// set return
				output = retir;
			} else {
				normal = new SOAPObjectiveCalculateOutput();
				normal.setRetirement(input.getRetirement());
				normal.setObjective(input.getObjective());
				normal.setInitial_amount(input.getInitial_Amount());
				normal.setRequired_amount(input.getRequired_Amount());
				normal.setMonthly_application(input.getMonthly_Application());
				normal.setInvestment_time(input.getInvestment_Time());
				normal.setInvestment_time_type(input.getInvestment_Time_Type());
				normal.setSuitability_tax(input.getSuitability_Tax());
				normal.setCurrent_age(input.getCurrent_Age());
				normal.setRetirement_start_age(input.getRetirement_Start_Age());
				normal.setRetirement_finish_age(input.getRetirement_Finish_Age());
				normal.setInvested_ammount(invested_ammount);

				normal.setinvested_ammount_rental(invested_ammount_rental);
				normal.setMissing_ammount(missing_ammount);
				normal.setExtra_credit(extra_credit);
				normal.setRetirement_time(retirement_time);

				normal.setContribution_time(contribution_time);
				normal.setTotal_initial_ammount_income(total_initial_ammount_income);
				normal.setTotal_monthly_applied_income(total_monthly_applied_income);
				normal.setInvested_ammount_rental(Invested_ammount_rental);
				normal.setFuture_revenue(future_revenue);
				normal.setRecomended_monthly_application(recomended_monthly_application);
				if (invested_ammount_rental != null || missing_ammount != null
						|| extra_credit != null || retirement_time != null) {
					normal.setError(false);
					normal.setMessage("");
				} else {
					normal.setError(true);
					normal.setMessage("Os par�metros obrigat�rios n�o podem estar nulos");
				}
				// set return 
				output = normal;
			}
		} else {
			normal = new SOAPObjectiveCalculateOutput();
			normal.setError(true);
			normal.setMessage("Os parametros de input s�o necess�rios para a execu��o dos c�lculos");
			output = normal;
		}
		return output;
	}
}
